package com.ceair.flight.refund.service.ota.impl;

import com.ceair.flight.refund.config.BaseConfig;
import com.ceair.flight.refund.dto.appmoblie.RefundCalReq;
import com.ceair.flight.refund.dto.appmoblie.RefundCalRes;
import com.ceair.flight.refund.dto.external.ApplyRequest;
import com.ceair.flight.refund.dto.external.ApplyResponse;
import com.ceair.flight.refund.dto.external.PriceSolutionRequest;
import com.ceair.flight.refund.dto.external.RefundDocs;
import com.ceair.flight.refund.dto.external.RefundPriceResultList;
import com.ceair.flight.refund.dto.external.RefundablePrice;
import com.ceair.flight.refund.dto.external.RefundableRequest;
import com.ceair.flight.refund.dto.external.RefundableResult;
import com.ceair.flight.refund.dto.external.RefundableResultList;
import com.ceair.flight.refund.dto.ota.CalcFeeRes;
import com.ceair.flight.refund.dto.ota.ReApplyReq;
import com.ceair.flight.refund.dto.ota.ReCalcFeeReq;
import com.ceair.flight.refund.dto.ota.RefundApplyReq;
import com.ceair.flight.refund.dto.ota.RefundApplyRes;
import com.ceair.flight.refund.dto.ota.RefundAttachment;
import com.ceair.flight.refund.dto.ota.RefundAttachmentReq;
import com.ceair.flight.refund.dto.ota.RefundAttachmentRes;
import com.ceair.flight.refund.dto.ota.RefundInfo;
import com.ceair.flight.refund.dto.ota.RefundOrderBean;
import com.ceair.flight.refund.dto.ota.RefundPassengerDto;
import com.ceair.flight.refund.dto.ota.RefundRes;
import com.ceair.flight.refund.dto.ota.RefundSegmentDto;
import com.ceair.flight.refund.dto.ota.RefundV2Req;
import com.ceair.flight.refund.location.dao.IFlightOrderDao;
import com.ceair.flight.refund.location.dao.IPaxDao;
import com.ceair.flight.refund.location.dao.IRefundApplyDao;
import com.ceair.flight.refund.location.dao.IRefundDetailDao;
import com.ceair.flight.refund.location.dao.IRefundSegDao;
import com.ceair.flight.refund.location.dao.IRefundTktDao;
import com.ceair.flight.refund.location.dt.enums.ApplyReason;
import com.ceair.flight.refund.location.dt.enums.ApplyUserType;
import com.ceair.flight.refund.location.dt.enums.CardTypeEnum;
import com.ceair.flight.refund.location.dt.enums.FlightOrderStatusEnum;
import com.ceair.flight.refund.location.dt.enums.MethodEnum;
import com.ceair.flight.refund.location.dt.enums.RefundStatus;
import com.ceair.flight.refund.location.model.FlightOrderDO;
import com.ceair.flight.refund.location.model.OrderDO;
import com.ceair.flight.refund.location.model.PaxDO;
import com.ceair.flight.refund.location.model.RefundApplyDO;
import com.ceair.flight.refund.location.model.RefundSegDO;
import com.ceair.flight.refund.location.model.RefundTktDO;
import com.ceair.flight.refund.location.model.SegmentDO;
import com.ceair.flight.refund.location.model.TaxFeeDO;
import com.ceair.flight.refund.location.model.TicketDO;
import com.ceair.flight.refund.location.service.IRefundLocationService;
import com.ceair.flight.refund.service.IOrderService;
import com.ceair.flight.refund.service.IRefundTicketService;
import com.ceair.flight.refund.service.external.calculator.IRefundFeeSolution;
import com.ceair.flight.refund.service.ota.IRefundService;
import com.ceair.flight.refund.util.CeairUtil;
import com.ceair.flight.refund.util.Constants;
import com.ceair.flight.refund.util.CurrencyUtil;
import com.ceair.flight.refund.util.DateUtil;
import com.ceair.flight.refund.util.GsonUtil;
import com.ceair.flight.refund.util.StringUtil;
import com.ceair.muibe.provider.tkt.DetrTktInfo;
import com.ceair.muibe.provider.tkt.DetrTktNoReq;
import com.ceair.muibe.provider.tkt.DetrTktNoRes;
import com.ceair.muibe.provider.tkt.OutTktService;
import com.ceair.muservice.basicdata.constant.LanguageCode;
import com.ceair.muservice.basicdata.dto.airport.AirportDto;
import com.ceair.muservice.basicdata.feign.util.AirportUtil;
import com.ceair.muservice.common.dto.BaseRes;
import com.ceair.muservice.common.exception.MuServiceException;
import com.google.gson.Gson;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;

@Service("refundService")
@Path("/ota")
public class RefundServiceImpl implements IRefundService {

    private static final Logger LOG = LoggerFactory.getLogger(RefundServiceImpl.class);
    @Autowired
    private IRefundLocationService refundLocationService;
    @Autowired
    private IOrderService orderService;
    @Autowired
    private OutTktService outTktService;
    @Autowired
    private IFlightOrderDao flightOrderDao;
    @Autowired
    private IRefundTicketService refundTicketService;

    @Autowired
    private IRefundApplyDao refundApplyDao;

    @Autowired
    private IRefundTktDao refundTktDao;

    @Autowired
    private IRefundDetailDao refundDetailDao;

    @Autowired
    private IPaxDao paxDao;

    @Autowired
    private IRefundFeeSolution eCFareRefundFeeSolution;

    @Autowired
    private IRefundSegDao refundSegDao;

    @Autowired
    private BaseConfig baseConfig;

    //    WIFI订单状态  1.新增  2 申请成功  3申请失败 4已取消
    private static String WIFI_APPL_SUCCESS = "2";

    public RefundCalRes calculator(RefundCalReq calReq) {
        RefundCalRes result = new RefundCalRes();
        boolean checkResult = checkReq(calReq);
        if (!checkResult) {
            result.setResultCode(Constants.ERROR_CODE);
            result.setResultMsg(Constants.PARAMS_ERROR_MSG);
            return result;
        }
        RefundableRequest request = buildCalRequest(calReq);

        RefundPriceResultList refundPriceResultList = null;
        try {
            refundPriceResultList = refundLocationService.calculatePrice(request);
        } catch (MuServiceException e) {
            String str = GsonUtil.toJson(calReq);
            LOG.error("calculator refund price error,param:" + str, e);
        }
        if (null == refundPriceResultList) {
            result.setResultCode(Constants.ERROR_CODE);
            result.setResultMsg(Constants.SERVER_ERROR_MSG);
            return result;
        }
        if (CollectionUtils.isEmpty(refundPriceResultList.getInvolPrice()) &&
                CollectionUtils.isEmpty(refundPriceResultList.getVolPrice())) {
            result.setResultCode("");
            result.setResultMsg("服务异常");
            return result;
        }

        return null;
    }

    @Override
    @POST
    @Path("/refundApply")
    @Consumes({"application/json"})
    @Produces(MediaType.APPLICATION_JSON)
    public RefundApplyRes refundApply(RefundApplyReq request) {
        LOG.info("start refundApply ,param:", GsonUtil.toJson(request));
        RefundApplyRes res = new RefundApplyRes();
        boolean isPass = checkRefundApply(request);
        if (!isPass) {
            res.setResultCode(Constants.ERROR_CODE);
            res.setResultMsg(Constants.PARAMS_ERROR_MSG);
            return res;
        }
        try {
            OrderDO orderDO = orderService.queryFlightOrderDetail(request.getOrderNo());
            Set<FlightOrderDO> flightOrderDOs = orderDO.getFlightOrders();
            List<FlightOrderDO> tktedFLightOrderList = new ArrayList<>();
            for (FlightOrderDO flightOrderDO : flightOrderDOs) {
                Integer orderStatus = flightOrderDO.getOrderSt();
                if (!Objects.equals(FlightOrderStatusEnum.TICKETED.getCode(), orderStatus)) {
                    continue;
                }
                tktedFLightOrderList.add(flightOrderDO);
            }

            res = createRefundApplyResult(orderDO, tktedFLightOrderList, request);
            res.setResultCode(Constants.SUCCESS_CODE);
            res.setResultMsg(Constants.SUCCESS_MSG);
        } catch (Exception e) {
            String str = GsonUtil.toJson(request);
            LOG.error("refundApply error,param: " + str, e);
            res.setResultCode(Constants.ERROR_CODE);
            res.setResultMsg(Constants.SERVER_ERROR_MSG);
            return res;
        } catch (Error error) {
            String str = GsonUtil.toJson(request);
            LOG.error("refundApply error,param: " + str, error);
            res.setResultCode(Constants.ERROR_CODE);
            res.setResultMsg(Constants.SERVER_ERROR_MSG);
            return res;
        }

        return res;
    }

    /**
     * 当审核被拒绝时，由非自愿退票转成自愿退票
     *
     * @param request
     * @return
     */
    @POST
    @Path("/reCalcFee")
    @Consumes({"application/json"})
    @Produces(MediaType.APPLICATION_JSON)
    @Override
    public CalcFeeRes reCalcFee(ReCalcFeeReq request) {
        LOG.info("非自愿转自愿处理开始，入参：" + new Gson().toJson(request));
        // 返回对象
        CalcFeeRes calcFeeRes = new CalcFeeRes();
        try {
            // 查询乘客退票申请信息
            RefundApplyDO refundApplyDO = refundApplyDao.getRefundApplyById(request.getApplyId());
            // 状态必须为非自愿且一审拒绝才能做后续处理
            if ("209".equals(refundApplyDO.getStatus()) && refundApplyDO.getIsVoluntary() == 0) {
                // 查询退票乘客及票信息
                RefundTktDO refundTkt = refundTktDao.selectByApplyId(request.getApplyId());
                Long paxId = refundTkt.getPaxId();
                //状态 1待开票、2已开票、3已退票、4已改期、5已升舱、6已挂起
                PaxDO paxDO = paxDao.queryPaxById(paxId);
                if (3 != paxDO.getModifySt()) {
                    calcFeeRes.setResultCode("1");
                    calcFeeRes.setMessage("抱歉，不允许非自愿转自愿退票");
                    return calcFeeRes;
                }

                OrderDO orderDO = orderService.queryFlightOrderDetail(request.getOrderNo());
                Set<FlightOrderDO> flightOrderDOS = orderDO.getFlightOrders();
                FlightOrderDO flightOrderDO = null;
                for (FlightOrderDO flightOrder : flightOrderDOS) {
                    if (flightOrder.getFlightOrderNo().equals(refundTkt.getFlightOrderNo())) {
                        flightOrderDO = flightOrder;
                        break;
                    }
                }

                BigDecimal ecRefundFee = getECRefundFee(refundTkt, orderDO, refundApplyDO, MethodEnum.REFUND_APPLY);
                BigDecimal oldRefundAmount = refundApplyDO.getRefundAmount();
                Long newRefundPoints = getRefundPoints(flightOrderDO, refundTkt);

                //更改退票单
                RefundTktDO refundTktNew = new RefundTktDO();
                refundTktNew.setId(refundTkt.getId());
                refundTktNew.setRefundFee(ecRefundFee);
                BigDecimal refundAmt = refundTkt.getRefundAmt().subtract(ecRefundFee);
                refundTktNew.setRefundAmt(refundAmt.compareTo(BigDecimal.ZERO) < 0 ? BigDecimal.ZERO : refundAmt);
                refundTktNew.setRefundPoints(newRefundPoints);
//                refundTktNew.setApplyId(refundTkt.getApplyId());
                refundTktNew.setId(refundTkt.getId());

                //更改退票申请
                RefundApplyDO refundApplyNew = new RefundApplyDO();
                refundApplyNew.setId(refundApplyDO.getId());
                refundApplyNew.setRefundFee(ecRefundFee);
                BigDecimal refundAmount = oldRefundAmount.subtract(ecRefundFee);
                refundApplyNew.setRefundAmount(refundAmount.compareTo(BigDecimal.ZERO) < 0 ? BigDecimal.ZERO : refundAmount);
                refundApplyNew.setRefundPoints(newRefundPoints);
                refundApplyNew.setIsVoluntary(1);
                refundApplyNew.setStatus("209");
                //TODO 待确认是否需要变更退票原因
                refundApplyNew.setClaimReason("10");

                boolean isSuccess = refundTicketService.recalFeeService(refundApplyNew, refundTktNew);
                if (isSuccess) {
                    calcFeeRes.setResultCode("0");
                    calcFeeRes.setMessage("非自愿转自愿退票处理成功");
                    calcFeeRes.setRefundAmount(refundApplyNew.getRefundAmount().doubleValue());
                    calcFeeRes.setRefundFee(refundApplyNew.getRefundFee().doubleValue());
                } else {
                    calcFeeRes.setResultCode("1");
                    calcFeeRes.setMessage("非自愿转自愿退票处理失败");
                }
            } else {
                calcFeeRes.setResultCode("2");
                calcFeeRes.setMessage("当前状态不是非自愿一审异常，退票处理失败");
                return calcFeeRes;
            }

            LOG.info("非自愿转自愿处理结束，出参：" + new Gson().toJson(calcFeeRes));
        } catch (Exception e) {
            LOG.error("非自愿转自愿退票处理失败" + e.getMessage());
            calcFeeRes.setResultCode("1");
            calcFeeRes.setMessage("非自愿转自愿退票处理失败");
            return calcFeeRes;
        } catch (Error ex) {
            LOG.error("非自愿转自愿退票处理失败" + ex.getMessage());
            calcFeeRes.setResultCode("1");
            calcFeeRes.setMessage("非自愿转自愿退票处理失败");
            return calcFeeRes;
        }
        return calcFeeRes;
    }

    private Long getRefundPoints(FlightOrderDO flightOrderDO, RefundTktDO refundTkt) {
        long pointsRefund = 0L;
        //判断是否是白金白金购买者
        String buyerTypeCode = flightOrderDO.getCardType();
        CardTypeEnum buyerType = null;
        if (buyerTypeCode != null && !buyerTypeCode.isEmpty()) {
            buyerType = CardTypeEnum.getByCode(buyerTypeCode);
        }
        if (buyerType == CardTypeEnum.PLT) {
            pointsRefund = getTotalPoints(flightOrderDO, refundTkt.getTicketNo());
            LOG.info("PLT buyer refund all points: {}", pointsRefund);
        }
        return pointsRefund;
    }

    private Long getTotalPoints(FlightOrderDO flightOrder, String ticketNo) {
        Set<PaxDO> paxes = flightOrder.getPaxs();
        for (PaxDO pax : paxes) {
            if (pax.getTktNo().equals(ticketNo)) {
                return pax.getPointAmount().longValue();
            }
        }
        return 0L;
    }

    private BigDecimal getECRefundFee(RefundTktDO refundTkt, OrderDO orderDO, RefundApplyDO refundApplyDO,MethodEnum methodEnum) {
        BigDecimal refundFee = BigDecimal.ZERO;
        Set<FlightOrderDO> flightOrderDOS = orderDO.getFlightOrders();
        FlightOrderDO flightOrderDO = null;
        for (FlightOrderDO flightOrder : flightOrderDOS) {
            if (flightOrder.getFlightOrderNo().equals(refundTkt.getFlightOrderNo())) {
                flightOrderDO = flightOrder;
                break;
            }
        }

        if (flightOrderDO.getCardType() != null && !"".equals(flightOrderDO.getCardType()) && CardTypeEnum.PLT.getCode().equals(flightOrderDO.getCardType())) {
            String pointTp = flightOrderDO.getPointTp();//pointTP有值，不为空说明是积分票
            if ("SJF".equals(pointTp)) {
                return BigDecimal.ZERO;
            }
        }

        PriceSolutionRequest priceSolutionRequest = buildPriceSolutionRequest(refundTkt, orderDO, refundApplyDO, flightOrderDO);
        RefundablePrice refundablePrice = eCFareRefundFeeSolution.getRefundFee(priceSolutionRequest,methodEnum);
        refundFee = refundablePrice.getFeeAmount();
        String currency = priceSolutionRequest.getCurrency();
        return CurrencyUtil.getProfitableValue(currency, refundFee);
    }

    private PriceSolutionRequest buildPriceSolutionRequest(RefundTktDO refundTkt, OrderDO orderDO, RefundApplyDO refundApplyDO, FlightOrderDO flightOrderDO) {
        PriceSolutionRequest priceSolutionRequest = new PriceSolutionRequest(refundTkt.getTicketNo());
        priceSolutionRequest.setBigOrder(orderDO);
        priceSolutionRequest.setPnrCancelDate(refundApplyDO.getPnrCancelDate());
        List<RefundSegDO> refundSegDOS = refundSegDao.queryByRfdTktId(refundTkt.getId());
        priceSolutionRequest.setFlightOrder(flightOrderDO);
        priceSolutionRequest.setRefundSegIndex(refundSegDOS.get(0).getIndexNo());
        return priceSolutionRequest;
    }

    private RefundApplyRes createRefundApplyResult(OrderDO orderDO, List<FlightOrderDO> tktedFLightOrderList, RefundApplyReq request) {
        RefundApplyRes res = new RefundApplyRes();
        RefundOrderBean refundOrderBean = new RefundOrderBean();
        res.setRefundOrderBean(refundOrderBean);
        Collection<RefundPassengerDto> refundPassengerDtos = new ArrayList<>();
        refundOrderBean.setPasCol(refundPassengerDtos);
        refundOrderBean.setAmount(orderDO.getScNy().toString());
        refundOrderBean.setOrderNo(orderDO.getOrderNo());
        //退票乘客的ID
        String refundPaxIdNo = request.getPaxIdNo();
        if (CollectionUtils.isEmpty(tktedFLightOrderList)) {
            return res;
        }
        Set<String> airportCodeSet = new HashSet<>();
        for (FlightOrderDO flightOrderDO : tktedFLightOrderList) {
            Set<PaxDO> paxDOS = flightOrderDO.getPaxs();
            for (PaxDO paxDO : paxDOS) {
                Set<SegmentDO> segmentDOS = paxDO.getSegments();
                for (SegmentDO segmentDO : segmentDOS) {
                    airportCodeSet.add(segmentDO.getDepAirpCd());
                    airportCodeSet.add(segmentDO.getArrAirpCd());
                }
            }
        }

        List<String> aiportCodeList = new ArrayList<>(airportCodeSet);
        List<AirportDto> airportDtos = AirportUtil.findByCodeList(aiportCodeList);
        Map<String, AirportDto> airportMap = convert(airportDtos);
        if (StringUtil.isBlank(refundPaxIdNo)) {
            //全退
            for (FlightOrderDO flightOrderDto : tktedFLightOrderList) {
                Set<PaxDO> paxDOList = flightOrderDto.getPaxs();
                Set<String> tktSet = new HashSet<>();
                for (PaxDO paxDto : paxDOList) {
                    Set<TicketDO> ticketDtos = paxDto.getTickets();
                    for (TicketDO ticketDto : ticketDtos) {
                        tktSet.add(ticketDto.getTktNo());
                    }
                }
                if (CollectionUtils.isEmpty(tktSet)) {
                    continue;
                }
                RefundableResultList refundableResultList = refundLocationService.checkRefundable(flightOrderDto.getFlightOrderNo(), tktSet,request.getCreateId(),request.getFfpNo());
                if (refundableResultList == null) {
                    LOG.error("checkRefundable result is null,tickNo:{}", Arrays.toString(tktSet.toArray()));
                    continue;
                }
                List<RefundableResult> refundableResults = refundableResultList.getRefundableResult();
                if (CollectionUtils.isEmpty(refundableResults)) {
                    LOG.error("checkRefundable result is null,tickNo:{}", Arrays.toString(tktSet.toArray()));
                    continue;
                }
                for (String ticketNo : tktSet) {
                    RefundableResult refundableResult = refundableResultList.getSingleResult(ticketNo);
                    if (refundableResult != null) {
                        boolean isRefundable = refundableResult.isRefundableInPolicy();
                        LOG.info("Ticket {} refundable:{} refundableIndex:{} unrefundable reason:{}", ticketNo, isRefundable, refundableResult.getRefundableIndex(), refundableResult.getReasonInPolicy());
                        RefundPassengerDto refundPassengerDto = createPassengerInfo(refundableResult, flightOrderDto, airportMap);
                        refundPassengerDtos.add(refundPassengerDto);
                    }
                }

            }
        } else {
            for (FlightOrderDO flightOrderDto : tktedFLightOrderList) {
                Set<PaxDO> paxDOList = flightOrderDto.getPaxs();
                Set<String> tktSet = new HashSet<>();
                for (PaxDO paxDto : paxDOList) {
                    if (refundPaxIdNo.equals(paxDto.getPassNo())) {
                        Set<TicketDO> ticketDtos = paxDto.getTickets();
                        for (TicketDO ticketDto : ticketDtos) {
                            tktSet.add(ticketDto.getTktNo());
                        }
                        break;
                    }
                }
                if (CollectionUtils.isEmpty(tktSet)) {
                    continue;
                }
                RefundableResultList refundableResultList = refundLocationService.checkRefundable(flightOrderDto.getFlightOrderNo(), tktSet,request.getCreateId(),request.getFfpNo());
                if (refundableResultList == null) {
                    continue;
                }

                List<RefundableResult> refundableResults = refundableResultList.getRefundableResult();
                if (CollectionUtils.isEmpty(refundableResults)) {
                    continue;
                }

                for (String ticketNo : tktSet) {
                    RefundableResult refundableResult = refundableResultList.getSingleResult(ticketNo);
                    if (refundableResult != null) {
                        boolean isRefundable = refundableResult.isRefundableInPolicy();
                        LOG.info("Ticket {} refundable:{} refundableIndex:{} unrefundable reason:{}", ticketNo, isRefundable, refundableResult.getRefundableIndex(), refundableResult.getReasonInPolicy());
                        if (isRefundable) {
                            RefundPassengerDto refundPassengerDto = createPassengerInfo(refundableResult, flightOrderDto, airportMap);
                            refundPassengerDtos.add(refundPassengerDto);
                        }
                    }
                }


            }
        }

        return res;
    }

    private Map<String, AirportDto> convert(List<AirportDto> airportDtos) {
        Map<String, AirportDto> map = new HashMap<>();
        for (AirportDto airportDto:airportDtos){
            String airportCd = airportDto.getCode();
            map.put(airportCd,airportDto);
        }
        return map;
    }

    private RefundPassengerDto createPassengerInfoNew(com.ceair.flight.refund.dto.external.RefundableResult refundableResult, FlightOrderDO flightOrderDO,  Map<String, AirportDto> airportMap) {
        RefundPassengerDto refundPassengerDto = new RefundPassengerDto();
        String tktNo = refundableResult.getTicketNo();
        int segRefundableIdx = refundableResult.getRefundableIndex();
        boolean isRefundable = refundableResult.isRefundableInPolicy();
        Set<PaxDO> paxDOSet = flightOrderDO.getPaxs();
        PaxDO refundablePax = null;
        for (PaxDO paxDO : paxDOSet) {
            String paxTktNo = paxDO.getTktNo();
            if (tktNo.equals(paxTktNo)) {
                refundablePax = paxDO;
                break;
            }
        }

        List<RefundSegmentDto> refundSegmentDtoList = new ArrayList<RefundSegmentDto>();
        Set<SegmentDO> segmentDOS = refundablePax.getSegments();
        for (SegmentDO seg : segmentDOS) {
            RefundSegmentDto segmentDto = new RefundSegmentDto();
            if (isRefundable) {
                int segSq = seg.getSegSq();
                if (segSq >= segRefundableIdx) {
                    segmentDto.setRefundable("0");//可退
                } else {
                    segmentDto.setRefundable("1");//不可退
                }
            } else {
                segmentDto.setRefundable("1");//不可退
            }

            segmentDto.setSegId(String.valueOf(seg.getSegId()));
            segmentDto.setOrgCode(seg.getDepAirpCd());
            segmentDto.setDstCode(seg.getArrAirpCd());
            AirportDto orgAirportInfo = airportMap.get(seg.getDepAirpCd());
            AirportDto destAirportInfo = airportMap.get(seg.getArrAirpCd());
            segmentDto.setOrgName(orgAirportInfo.getName(LanguageCode.EN));
            segmentDto.setDstName(destAirportInfo.getName(LanguageCode.EN));
            segmentDto.setAircraftType(seg.getEquipment());
            segmentDto.setPrice(seg.getScny().toString());
            segmentDto.setFlightNo(seg.getFlightNo());
            if (seg.getIsinter()) {
                segmentDto.setTotalTax(seg.getTaxAm().doubleValue());
            } else {
                Set<TaxFeeDO> taxFeeDOS = seg.getTaxFees();
                BigDecimal taxYQ = BigDecimal.ZERO;
                BigDecimal taxAirport = BigDecimal.ZERO;
                for (TaxFeeDO taxFeeDO : taxFeeDOS) {
                    if (Constants.TAX_TYPE_YQ.equals(taxFeeDO.getTaxTp())) {
                        taxYQ = taxFeeDO.getTaxAm();
                        break;
                    }
                }
                taxAirport = seg.getTaxAm().subtract(taxYQ);
                segmentDto.setFuelTax(taxYQ.toString());
                segmentDto.setAirportTax(taxAirport.toString());
            }
            segmentDto.setDesc("");
            segmentDto.setSeatClass(seg.getClassTp());
            String depDT = DateUtil.toString(seg.getDepDt(), DateUtil.yyyy_MM_dd);
            String depTime = depDT + " " + seg.getDepTm();
            String arrDT = DateUtil.toString(seg.getArrDt(), DateUtil.yyyy_MM_dd);
            String arrTime = arrDT + " " + seg.getArrTm();
            segmentDto.setDepTime(depTime);
            segmentDto.setArrTime(arrTime);
            refundSegmentDtoList.add(segmentDto);
        }

        refundPassengerDto.setPasId(String.valueOf(refundablePax.getPassengerId()));
        //TODO
        refundPassengerDto.setNameCn(refundablePax.getPaxFullName());
        refundPassengerDto.setIdType(refundablePax.getPassTp());
        refundPassengerDto.setIdNo(refundablePax.getPassNo());
        refundPassengerDto.setPsgType(refundablePax.getPassengerTp());
        refundPassengerDto.setTicketNo(refundablePax.getTktNo());
        //TODO
        //会员卡
        refundPassengerDto.setMeligCard("");
        refundPassengerDto.setRefundSegmentDtoList(refundSegmentDtoList);

        return refundPassengerDto;
    }

    private RefundPassengerDto createPassengerInfo(RefundableResult refundableResult, FlightOrderDO flightOrderDO, Map<String, AirportDto> airportMap) {
        RefundPassengerDto refundPassengerDto = new RefundPassengerDto();
        String tktNo = refundableResult.getTicketNo();
        int segRefundableIdx = refundableResult.getRefundableIndex();
        boolean isRefundable = refundableResult.isRefundableInPolicy();
        Set<PaxDO> paxDOSet = flightOrderDO.getPaxs();
        PaxDO refundablePax = null;
        for (PaxDO paxDO : paxDOSet) {
            String paxTktNo = paxDO.getTktNo();
            if (tktNo.equals(paxTktNo)) {
                refundablePax = paxDO;
                break;
            }
        }

        List<RefundSegmentDto> refundSegmentDtoList = new ArrayList<RefundSegmentDto>();
        Set<SegmentDO> segmentDOS = refundablePax.getSegments();
        for (SegmentDO seg : segmentDOS) {
            RefundSegmentDto segmentDto = new RefundSegmentDto();
            if (isRefundable) {
                int segSq = seg.getSegSq();
                if (segSq >= segRefundableIdx) {
                    segmentDto.setRefundable("0");//可退
                } else {
                    segmentDto.setRefundable("1");//不可退
                }
            } else {
                segmentDto.setRefundable("1");//不可退
            }

            segmentDto.setSegId(String.valueOf(seg.getSegId()));
            segmentDto.setOrgCode(seg.getDepAirpCd());
            segmentDto.setDstCode(seg.getArrAirpCd());
            AirportDto orgAirportInfo = airportMap.get(seg.getDepAirpCd());
            AirportDto destAirportInfo = airportMap.get(seg.getArrAirpCd());
            segmentDto.setOrgName(orgAirportInfo.getName(LanguageCode.EN));
            segmentDto.setDstName(destAirportInfo.getName(LanguageCode.EN));
            segmentDto.setAircraftType(seg.getEquipment());
            segmentDto.setPrice(seg.getScny().toString());
            segmentDto.setFlightNo(seg.getFlightNo());
            if (seg.getIsinter()) {
                segmentDto.setTotalTax(seg.getTaxAm().doubleValue());
            } else {
                Set<TaxFeeDO> taxFeeDOS = seg.getTaxFees();
                BigDecimal taxYQ = BigDecimal.ZERO;
                BigDecimal taxAirport = BigDecimal.ZERO;
                for (TaxFeeDO taxFeeDO : taxFeeDOS) {
                    if (Constants.TAX_TYPE_YQ.equals(taxFeeDO.getTaxTp())) {
                        taxYQ = taxFeeDO.getTaxAm();
                        break;
                    }
                }
                taxAirport = seg.getTaxAm().subtract(taxYQ);
                segmentDto.setFuelTax(taxYQ.toString());
                segmentDto.setAirportTax(taxAirport.toString());
            }
            segmentDto.setDesc("");
            segmentDto.setSeatClass(seg.getClassTp());
            String depDT = DateUtil.toString(seg.getDepDt(), DateUtil.yyyy_MM_dd);
            String depTime = depDT + " " + seg.getDepTm();
            String arrDT = DateUtil.toString(seg.getArrDt(), DateUtil.yyyy_MM_dd);
            String arrTime = arrDT + " " + seg.getArrTm();
            segmentDto.setDepTime(depTime);
            segmentDto.setArrTime(arrTime);
            refundSegmentDtoList.add(segmentDto);
        }

        refundPassengerDto.setPasId(String.valueOf(refundablePax.getPassengerId()));
        //TODO
        refundPassengerDto.setNameCn(refundablePax.getPaxFullName());
        refundPassengerDto.setIdType(refundablePax.getPassTp());
        refundPassengerDto.setIdNo(refundablePax.getPassNo());
        refundPassengerDto.setPsgType(refundablePax.getPassengerTp());
        refundPassengerDto.setTicketNo(refundablePax.getTktNo());
        //TODO
        //会员卡
        refundPassengerDto.setMeligCard("");
        refundPassengerDto.setRefundSegmentDtoList(refundSegmentDtoList);

        return refundPassengerDto;
    }


    private boolean checkRefundApply(RefundApplyReq req) {
        boolean result = true;
        String channelCode = req.getSalesChannel();
        String orderNo = req.getOrderNo();
        if (StringUtil.isBlank(channelCode) || StringUtil.isBlank(orderNo)) {
            return false;
        }
        return result;
    }


    private RefundableRequest buildCalRequest(RefundCalReq calReq) {
        RefundableRequest request = new RefundableRequest();
        request.setFlightOrderNo(calReq.getFlightOrderNo());
        String ticketStr = calReq.getTicket();
        String[] tktArr = ticketStr.split(",");
        Set<String> tickets = new HashSet<String>(Arrays.asList(tktArr));
        request.setTickets(tickets);
        return request;
    }

    private boolean checkReq(RefundCalReq calReq) {
        boolean result = false;
        String flightOrderNo = calReq.getFlightOrderNo();
        String orderNo = calReq.getOrderNo();
        String ticket = calReq.getTicket();
        if (StringUtils.isEmpty(flightOrderNo)) {
            return false;
        }
        if (StringUtils.isEmpty(orderNo)) {
            return false;
        }
        if (StringUtils.isEmpty(ticket)) {
            return false;
        }
        return true;
    }

//    private List<WifiOrderVO> builderWifiOrderInfo(Set<WifiOrderDO> wifiOrderDOS, Map<String, AirportInfoForSiteVO> aiportMap) {
//        List<WifiOrderVO> result = new ArrayList<>();
//        if (CollectionUtils.isEmpty(wifiOrderDOS)) {
//            return result;
//        }
//        for (WifiOrderDO wifiOrderDO : wifiOrderDOS) {
//            WifiOrderVO wifiOrderVO = new WifiOrderVO();
//            result.add(wifiOrderVO);
//            wifiOrderVO.setCurrency(wifiOrderDO.getCurrency());
//            wifiOrderVO.setOrderNo(wifiOrderDO.getOrderNo());
//            wifiOrderVO.setWifiOrderNo(wifiOrderDO.getWifiOrderNo());
//            wifiOrderVO.setTotalprice(wifiOrderDO.getFCNY().doubleValue());
//            List<PaxSegsVO> paxSegsVOList = new ArrayList<>();
//            wifiOrderVO.setPaxSegsVOList(paxSegsVOList);
//            Set<WifiPassengerDO> wifiPassengerDOS = wifiOrderDO.getWifiPaxDto();
//            for (WifiPassengerDO wifiPassengerDO : wifiPassengerDOS) {
//                PaxSegsVO paxSegsVO = new PaxSegsVO();
//                paxSegsVOList.add(paxSegsVO);
//                paxSegsVO.setPaxId(wifiPassengerDO.getFlightPaxNo());
//                paxSegsVO.setPrice(wifiPassengerDO.getFCNY().doubleValue());
//                paxSegsVO.setCurrency(wifiOrderDO.getCurrency());
//                List<SegVO> segVOList = new ArrayList<>();
//                paxSegsVO.setSegVOList(segVOList);
//                Set<WifiSegDO> wifiSegDOS = wifiPassengerDO.getWifiSegmentDto();
//                for (WifiSegDO wifiSegDO : wifiSegDOS) {
//                    SegVO segVO = new SegVO();
//                    segVOList.add(segVO);
//                    segVO.setArriveAirPortCd(wifiSegDO.getArrAirpCd());
//                    segVO.setArriveAirPortName(aiportMap.get(segVO.getArriveAirPortCd()).getAirportName());
//                    segVO.setArrTerm(wifiSegDO.getArrTerm());
//                    segVO.setCabin(wifiSegDO.getClassTp());
//                    segVO.setDepartAirPortCd(wifiSegDO.getDepAirpCd());
//                    segVO.setDepartAirPortName(aiportMap.get(segVO.getDepartAirPortCd()).getAirportName());
//                    segVO.setDepterm(wifiSegDO.getDepTerm());
//                    segVO.setMarketFlightNo(wifiSegDO.getFlightNo());
//                    segVO.setOperateFlightNo(wifiSegDO.getRealFlightNo());
//                    segVO.setSegId(Long.parseLong(wifiSegDO.getFlightSegId()));
//                    segVO.setSegSQ(wifiSegDO.getSegSq());
//                    segVO.setTktno(wifiSegDO.getTktNo());
//                }
//            }
//
//        }
//        return result;
//    }
//
//    private List<EmdOrderVO> builderEmdOrderInfo(Set<EmdOrderDO> emdOrderDOSet, Map<String, AirportInfoForSiteVO> aiportMap) {
//        List<EmdOrderVO> result = new ArrayList<>();
//        if (CollectionUtils.isEmpty(emdOrderDOSet)) {
//            return result;
//        }
//        for (EmdOrderDO emdOrderDO : emdOrderDOSet) {
//            EmdOrderVO emdOrderVO = new EmdOrderVO();
//            result.add(emdOrderVO);
//            emdOrderVO.setEmdOrderNo(emdOrderDO.getEmdOrderNo());
//            emdOrderVO.setCurrency(emdOrderDO.getCurrency());
//            emdOrderVO.setOrderNo(emdOrderDO.getOrderNo());
//            emdOrderVO.setTotalprice(emdOrderDO.getFCNY().doubleValue());
//            List<PaxSegsVO> paxSegsVOList = new ArrayList<>();
//            Set<EmdPassengerDO> emdPassengerDOSet = emdOrderDO.getEmdPaxDto();
//            for (EmdPassengerDO emdPassengerDO : emdPassengerDOSet) {
//                PaxSegsVO paxSegsVO = new PaxSegsVO();
//                paxSegsVOList.add(paxSegsVO);
//                paxSegsVO.setPaxId(String.valueOf(emdPassengerDO.getFlightPaxNo()));
//                paxSegsVO.setCurrency(emdPassengerDO.getCurrency());
//                paxSegsVO.setPrice(emdPassengerDO.getFCNY().doubleValue());
//                List<SegVO> segVOList = new ArrayList<>();
//                paxSegsVO.setSegVOList(segVOList);
//                Set<EmdSegDO> emdSegDOSet = emdPassengerDO.getEmdSegmentDto();
//                for (EmdSegDO emdSegDO : emdSegDOSet) {
//                    String tktNo = emdSegDO.getTktNo();
//                    Set<EmdTktDO> emdTktDOS = emdSegDO.getEmdTicketDO();
//                    SegVO segVO = new SegVO();
//                    segVOList.add(segVO);
//                    segVO.setArriveAirPortCd(emdSegDO.getArrAirpCd());
//                    segVO.setArriveAirPortName(aiportMap.get(segVO.getArriveAirPortCd()).getAirportName());
//                    segVO.setArrTerm(emdSegDO.getArrTerm());
//                    segVO.setCabin(emdSegDO.getClassTp());
//                    segVO.setDepartAirPortCd(emdSegDO.getDepAirpCd());
//                    segVO.setDepartAirPortName(aiportMap.get(segVO.getDepartAirPortCd()).getAirportName());
//                    segVO.setDepterm(emdSegDO.getDepTerm());
//                    segVO.setMarketFlightNo(emdSegDO.getFlightNo());
//                    segVO.setOperateFlightNo(emdSegDO.getRealFlightNo());
//                    segVO.setSegId(Long.parseLong(emdSegDO.getFlightSegId()));
//                    segVO.setSegSQ(emdSegDO.getSegSq());
//                    segVO.setTktno(tktNo);
//                }
//            }
//        }
//        return result;
//    }
//
//    private List<FlightOrderVO> builderFlightOrderInfo(List<FlightOrderDO> flightOrderList, Map<String, AirportInfoForSiteVO> aiportMap) {
//        LOG.debug("begin builderFlightOrderInfo...");
//        List<FlightOrderVO> result = new ArrayList<>();
//        if (CollectionUtils.isEmpty(flightOrderList)) {
//            return result;
//        }
//        for (FlightOrderDO flightOrderDto : flightOrderList) {
//            Set<PaxDO> paxDtoList = flightOrderDto.getPaxs();
//            Set<String> tktSet = new HashSet<>();
//            for (PaxDO paxDto : paxDtoList) {
//                Set<TicketDO> ticketDtos = paxDto.getTickets();
//                for (TicketDO ticketDto : ticketDtos) {
//                    tktSet.add(ticketDto.getTktNo());
//                }
//            }
//            RefundableResultList refundableResultList = refundLocationService.checkRefundable(flightOrderDto.getFlightOrderNo(), tktSet);
//            if (refundableResultList == null) {
//                continue;
//            }
//            List<RefundableResult> refundableResults = refundableResultList.getRefundableResult();
//            if (CollectionUtils.isEmpty(refundableResults)) {
//                continue;
//            }
//            FlightOrderVO flightOrderVO = new FlightOrderVO();
//            flightOrderVO.setOrderNo(flightOrderDto.getOrderNo());
//            flightOrderVO.setFlightOrderNo(flightOrderDto.getFlightOrderNo());
//            flightOrderVO.setCurrency(flightOrderDto.getCurrency());
//            flightOrderVO.setTotalPrice(flightOrderDto.getFcNy().doubleValue());
//            flightOrderVO.setTotalTax(flightOrderDto.getTaxAm().doubleValue());
//            List<PaxSegsVO> paxSegsVOList = new ArrayList<>();
//            flightOrderVO.setPaxSegsVOList(paxSegsVOList);
//            result.add(flightOrderVO);
//            for (PaxDO paxDto : paxDtoList) {
//                PaxSegsVO paxSegsVO = new PaxSegsVO();
//                paxSegsVOList.add(paxSegsVO);
//                paxSegsVO.setPaxId(String.valueOf(paxDto.getPassengerId()));
//                paxSegsVO.setCurrency(paxDto.getCurrency());
//                paxSegsVO.setPrice(paxDto.getFcny().doubleValue());
//                paxSegsVO.setTax(paxDto.getTaxAm().doubleValue());
//                Set<TaxFeeDO> taxFeeDOS = paxDto.getTaxFees();
////                paxSegsVO.setTaxDetailList();
//                List<SegVO> segVOList = new ArrayList<>();
//                paxSegsVO.setSegVOList(segVOList);
//                Set<SegmentDO> segmentDtoList = paxDto.getSegments();
//                Set<TicketDO> ticketDtoList = paxDto.getTickets();
//                for (SegmentDO segmentDto : segmentDtoList) {
//                    Long tickID = segmentDto.getTktID();
//                    SegVO segVO = new SegVO();
//                    segVOList.add(segVO);
//                    segVO.setArriveAirPortCd(segmentDto.getArrAirpCd());
//                    segVO.setArriveAirPortName(aiportMap.get(segVO.getArriveAirPortCd()).getAirportName());
//                    segVO.setArrTerm(segmentDto.getArrTerm());
//                    segVO.setCabin(segmentDto.getClassTp());
//                    segVO.setDepartAirPortCd(segmentDto.getDepAirpCd());
//                    segVO.setDepartAirPortName(aiportMap.get(segVO.getDepartAirPortCd()).getAirportName());
//                    segVO.setDepterm(segmentDto.getDepTerm());
//                    segVO.setEIcommnet(segmentDto.getEcomment());
//                    segVO.setIsinter(segmentDto.getIsinter() == true ? "1" : "0");
//                    segVO.setMarketFlightNo(segmentDto.getFlightNo());
//                    segVO.setOperateFlightNo(segmentDto.getRealFlightNo());
//                    segVO.setSegId(segmentDto.getSegId());
//                    segVO.setSegSQ(segmentDto.getSegSq());
//                    segVO.setSegStatus(segmentDto.getSegSt());
//                    for (TicketDO ticketDto : ticketDtoList) {
//                        long id = ticketDto.getTktId();
//                        if (tickID == id) {
//                            segVO.setTktno(ticketDto.getTktNo());
//                            String ticketNo = ticketDto.getTktNo();
//                            RefundableResult refundableResult = refundableResultList.getSingleResult(ticketNo);
//                            if (refundableResult != null) {
//                                boolean isRefundable = refundableResult.isRefundableInPolicy();
//                                LOG.info("Ticket {} refundable:{} refundableIndex:{} unrefundable reason:{}", ticketNo, isRefundable, refundableResult.getRefundableIndex(), refundableResult.getReasonInPolicy());
//                                if (isRefundable) {
//                                    if (segmentDto.getSegSq() >= refundableResult.getRefundableIndex()) {
//                                        segVO.setIsRefundable("1");
//                                    }
//                                }
//                            }
//                        }
//                    }
//                }
//            }
//
//        }
//        return result;
//    }

    private boolean isEmpty(String source) {
        return StringUtils.isEmpty(source);
    }

    @Override
    @POST
    @Path("/refundV2")
    @Consumes({"application/json"})
    @Produces(MediaType.APPLICATION_JSON)
    public RefundRes refundV2(RefundV2Req request) {
        LOG.info("refundV2 入参：" + GsonUtil.toJson(request));
        RefundRes refundRes = new RefundRes();
        ApplyRequest applyRequest = new ApplyRequest();
        //根据大订单号查询订单详细
        List<FlightOrderDO> listByOrderNo = flightOrderDao.getFlightOrderListByOrderNo(request.getOrderNo());
        FlightOrderDO flightOrderDO = listByOrderNo.get(0);
        String flightOrderNo = flightOrderDO.getFlightOrderNo();
        //Set<TicketDO> tickets = flightOrderDO.getTickets();
        Set<PaxDO> paxs = flightOrderDO.getPaxs();
        Set<String> ticketSets = new HashSet<String>();
        //根据退票乘客ID查出退票号
        List<RefundInfo> refundInfos = request.getRefundInfos();
        for (RefundInfo refundInfo : refundInfos) {
            Long id = refundInfo.getId();
            for (PaxDO pax : paxs) {
                if (id.equals(pax.getPassengerId())) {
                    ticketSets.add(pax.getTktNo());
                }
            }
        }
        //收集退票号
        applyRequest.setTickets(ticketSets);
        applyRequest.setFlightOrderNo(flightOrderNo);
        //applyRequest.setClaimerId(claimerId);
        applyRequest.setSalesChannel(request.getSalesChannel());
        applyRequest.setChannelNo(request.getSalesChannel());
        applyRequest.setClaimerName(request.getAppName());
        applyRequest.setClaimerPhone(request.getAppContact());
        applyRequest.setClaimerEmail(request.getAppContact());
        applyRequest.setClaimerType(ApplyUserType.SYSTEM);
        //applyRequest.setClaimSource(request.gets); 申请退票用户IP
        //applyRequest.setCountry(country);国家
        //applyRequest.setLanguage(language);语言
        applyRequest.setFlightOrderNo(flightOrderDO.getFlightOrderNo());
        //退票类型:281：自愿退票 282：非自愿退票；283：航班延误或取消（航空公司原因）286：病退 287：另购客票
        String applyType = request.getApplyType();
        switch (applyType) {
            case "281":
                applyRequest.setClaimReason(ApplyReason.getByCode("10"));
                break;
            case "282":
                applyRequest.setClaimReason(ApplyReason.getByCode("24"));
                break;
            case "283":
                applyRequest.setClaimReason(ApplyReason.getByCode("21"));
                break;
            case "286":
                applyRequest.setClaimReason(ApplyReason.getByCode("22"));
                List<RefundAttachment> attachmentsV2 = request.getAttachments();
                List<RefundDocs> attachmentList = new ArrayList<RefundDocs>();
                applyRequest.getAttachments();
                for (RefundAttachment refundAttachment : attachmentsV2) {
                    RefundDocs refundDocs = new RefundDocs();
                    //TODO 将Content 附件内容 保存至cdn返回保存路径,@ 王珽
                    String urlContent = savedContent(refundAttachment.getContent());
                    refundDocs.setAttchments(urlContent);
                    refundDocs.setContentDesc(refundAttachment.getName());
                    attachmentList.add(refundDocs);
                }
                applyRequest.setAttachments(attachmentList);
                break;
            case "287":
                applyRequest.setClaimReason(ApplyReason.getByCode("23"));
                //另购客票号
                String repurchaseTickets = request.getRepurchaseTicket();
                LOG.info("另购客票 :" + repurchaseTickets);
                String[] repurchaseTicket = repurchaseTickets.split(",");
                if (repurchaseTicket.length == 0 || null == repurchaseTicket) {
                    LOG.error("退票原因:287 另购客票,未填写另购客票号");
                    refundRes.setResultMsg("失败原因:另购客票,未填写另购客票号");
                    refundRes.setReturnMsg("退票失败");
                    refundRes.setResultCode("1");
                    return refundRes;
                }
                DetrTktNoReq detrTktNoReq = new DetrTktNoReq();
                //TODO 确认渠道,否则报错
                detrTktNoReq.setUser(CeairUtil.getUserInfo(request.getSalesChannel()));
                for (String ticket : repurchaseTicket) {
                    detrTktNoReq.setTktNo(request.getRepurchaseTicket());
                    //TODO 从航信提取另购客票号,服务未起
                    DetrTktNoRes detrTktNoRes = this.outTktService.detrTktNo(detrTktNoReq);
                    if (null == detrTktNoRes || null == detrTktNoRes.getTktInfo()) {
                        LOG.error("另购客票号: 不存在,从航信未查询到另购客票,不允许以另购客票为理由退票");
                        refundRes.setResultMsg("失败原因:另购客票号: 不存在,从航信未查询到另购客票,不允许以另购客票为理由退票");
                        refundRes.setReturnMsg("退票失败");
                        refundRes.setResultCode("1");
                        return refundRes;
                    }
                    LOG.info("申请退票人：" + request.getAppName() + " == 另购票号" + ticket + "票号查询结果：" + GsonUtil.toJson(detrTktNoRes));
                    //新购客票
                    DetrTktInfo tktInfo = detrTktNoRes.getTktInfo();
                    //判断退票信息与另购票信息
                    for (RefundInfo refundInfo : refundInfos) {
                        Long id = refundInfo.getId();
                        for (PaxDO pax : paxs) {
                            //另购票规则
                            if (id.equals(pax.getPassengerId())) {
                                //退票销售价
                                BigDecimal scny = pax.getScny();
                                //另购客票总价
                                BigDecimal totalAmount = new BigDecimal(tktInfo.getTotalAmount());
                                if (totalAmount.compareTo(scny) == -1) {
                                    LOG.error("退票原因:287 ;另购客票销售价:" + totalAmount + "小于" + "退票客票销售价" + scny + ",不允许走287流程退票");
                                    refundRes.setResultMsg("失败原因:退票原因:287 ;另购客票销售价:" + totalAmount + "小于" + "退票客票销售价" + scny + ",不允许走287流程退票");
                                    refundRes.setReturnMsg("退票失败");
                                    refundRes.setResultCode("1");
                                    return refundRes;
                                }
                                //退票乘客姓名
                                String name = pax.getPassengerFirstName() + pax.getPassengerMiddleName() + pax.getPassengerLastName();
                                //新购客票乘客姓名
                                String passengerName = tktInfo.getPassengerName();
                                if (!name.equals(passengerName)) {
                                    LOG.error("退票原因:287 ;另购客票销售价:" + totalAmount + "小于" + "退票客票销售价" + scny + ",不允许走287流程退票");
                                    refundRes.setResultMsg("失败原因:乘客姓名不一致,退票乘客姓名 " + name + ",新购客票乘客姓名 " + passengerName);
                                    refundRes.setReturnMsg("退票失败");
                                    refundRes.setResultCode("1");
                                    return refundRes;
                                }
                                //退票乘客航程
                                //退票乘客航班
                                //退票乘客日期
                                //退票乘客机票价格
                                //另购票是否已使用
                            }
                        }
                    }
                }
                break;
            default:
                applyRequest.check();
                break;
        }
        applyRequest.setClaimDesc(request.getReason());
        ApplyResponse applyRfdTkt = refundTicketService.applyRfdTkt(applyRequest);
        System.out.println("退票响应" + GsonUtil.toJson(applyRfdTkt));
        boolean success = applyRfdTkt.isSuccess();
        refundRes.setResultCode(applyRfdTkt.getResultCode());
        refundRes.setResultMsg(applyRfdTkt.getResultMsg());
        if (!success) {
            refundRes.setReturnMsg("退票失败");
        } else {
            refundRes.setResultMsg("退票成功");
        }
        //20190102如果当前退票原因是病退，且上传附件，进行以下操作
//        boolean uploadSuccess = uploadAttachments(request, ticketSets);
//		refundRes.setResultCode(applyRfdTkt.getCode());
//		refundRes.setResultMsg(applyRfdTkt.getMsg());
//		refundRes.setReturnMsg("退票成功");
//        if (!uploadSuccess){
//            refundRes.setReturnMsg("退票申请成功，上传附件内容异常");
//        }
        return refundRes;
    }

    private boolean uploadAttachments(RefundV2Req request, Set<String> ticketSets) {
        boolean result = true;
        String applyType = request.getApplyType();
        //判断是否病退
        if (!"286".equals(applyType)) {
            return true;
        }
        List<RefundAttachment> attachments = request.getAttachments();
        if (CollectionUtils.isEmpty(attachments)) {
            return true;
        }

        List<String> tktList = new ArrayList<>();
        List<Long> applyIdList = null;
        try {
            applyIdList = refundDetailDao.getRefundApplyIdByticketId(tktList);
        } catch (Exception e) {
            LOG.error("Query RefundApplyIdByticketId error ", e);
            return false;
        }
        if (CollectionUtils.isEmpty(applyIdList)) {
            return true;
        }
        List<RefundAttachmentReq> leftReq = new ArrayList<>();
        for (RefundAttachment refundAttachment : attachments) {
            for (Long applyId : applyIdList) {
                RefundAttachmentReq req = new RefundAttachmentReq();
                req.setApplyId(applyId);
                req.setOrderNo(request.getOrderNo());
                req.setContent(refundAttachment.getContent());
                req.setName(refundAttachment.getName());
                req.setSalesChannel(req.getSalesChannel());
                BaseRes res = addAttachment(req);
                if (!Constants.SUCCESS_CODE.equals(res.getResultCode())) {
                    leftReq.add(req);
                }
            }
        }

        //重新上传之前上传失败的附件
        Iterator<RefundAttachmentReq> it = leftReq.iterator();
        while (it.hasNext()) {
            RefundAttachmentReq req = it.next();
            BaseRes res = addAttachment(req);
            if (Constants.SUCCESS_CODE.equals(res.getResultCode())) {
                it.remove();
            }
        }
        if (!CollectionUtils.isEmpty(leftReq)) {
            return false;
        }
        return result;
    }

    /**
     * @param content
     * @return
     */
    private String savedContent(byte[] content) {
        // TODO 将Content 附件内容上传保存至cdn返回保存路径,@ 王珽
        return "urlContent";
    }

    @Override
    @POST
    @Path("/reApply")
    @Consumes({"application/json"})
    @Produces(MediaType.APPLICATION_JSON)
    public RefundRes reApply(ReApplyReq request) {
        boolean result = checkReApplyParam(request);
        RefundRes res = new RefundRes();
        if (!result) {
            res.setResultCode(Constants.ERROR_CODE);
            res.setResultMsg(Constants.PARAMS_ERROR_MSG);
            return res;
        }
        try {
            RefundApplyDO refundApplyDO = refundLocationService.getRefundApply(request.getApplyId());
            if (refundApplyDO == null) {
                res.setResultCode(Constants.ERROR_CODE);
                res.setResultMsg(Constants.SERVER_ERROR_MSG);
                return res;
            }
            //TODO
            String applyStatus = refundApplyDO.getStatus();
            if (!RefundStatus.FIRST_AUDIT_EXCEPTION.getCode().equals(applyStatus)) {
                res.setResultCode("2");
                res.setResultMsg("当前退票状态不允许重新提交申请");
                return res;
            }

            RefundApplyDO refundApply = new RefundApplyDO();
            refundApply.setId(refundApplyDO.getId());
            refundApply.setStatus(RefundStatus.WAIT_FIRST_AUDIT.getCode());
            boolean isSuccess = refundLocationService.reApply(refundApply);
            if (isSuccess) {
                res.setResultCode(Constants.SUCCESS_CODE);
                res.setResultMsg(Constants.SUCCESS_MSG);
                res.setReturnMsg(Constants.SUCCESS_MSG);
            } else {
                res.setResultCode(Constants.ERROR_CODE);
                res.setResultMsg(Constants.SERVER_ERROR_MSG);
            }
        } catch (Exception e) {
            LOG.error("ReApply error:", e);
            res.setResultCode(Constants.ERROR_CODE);
            res.setResultMsg(Constants.SERVER_ERROR_MSG);
            return res;
        } catch (Error ex) {
            LOG.error("ReApply error:", ex);
            res.setResultCode(Constants.ERROR_CODE);
            res.setResultMsg(Constants.SERVER_ERROR_MSG);
            return res;
        }

        return res;
    }

    @Override
    public BaseRes addAttachment(RefundAttachmentReq request) {
        RefundAttachmentRes res = new RefundAttachmentRes();
        boolean isPass = checkAttachmentParam(request);
        if (!isPass) {
            res.setResultCode(Constants.ERROR_CODE);
            res.setResultMsg(Constants.PARAMS_ERROR_MSG);
            return res;
        }
        String param = GsonUtil.toJson(request);
        try {
            String result = refundLocationService.getExternalData("", param);
            if (StringUtil.isBlank(result)) {
                res.setResultCode(Constants.ERROR_CODE);
                res.setResultMsg(Constants.SERVER_ERROR_MSG);
            }
            BaseRes resultRes = GsonUtil.fromJson(result, BaseRes.class);
            return resultRes;
        } catch (Exception e) {
            LOG.error("AddAttachment error:", e);
            res.setResultCode(Constants.ERROR_CODE);
            res.setResultMsg(Constants.SERVER_ERROR_MSG);
            return res;
        } catch (Error error) {
            LOG.error("AddAttachment error:", error);
            res.setResultCode(Constants.ERROR_CODE);
            res.setResultMsg(Constants.SERVER_ERROR_MSG);
            return res;
        }

    }

    private boolean checkAttachmentParam(RefundAttachmentReq request) {
        long applyId = request.getApplyId();
        byte[] content = request.getContent();
        String name = request.getName();
        String orderNo = request.getOrderNo();
        String salesChannel = request.getSalesChannel();
        if (applyId <= 0l) {
            return false;
        }
        if (content == null || content.length == 0) {
            return false;
        }
        if (StringUtil.isBlank(name) || StringUtil.isBlank(orderNo) || StringUtil.isBlank(salesChannel)) {
            return false;
        }
        return true;
    }

    private boolean checkReApplyParam(ReApplyReq request) {
        boolean result = true;
        String salesChannel = request.getSalesChannel();
        long applyId = request.getApplyId();
        String orderNo = request.getOrderNo();
        if (StringUtil.isBlank(salesChannel) || StringUtil.isBlank(orderNo) || applyId <= 0) {
            result = false;
        }
        return result;
    }
}